package com.cd.university.service.impl;

import com.cd.university.common.RestResult;
import com.cd.university.common.UniversityConstants;
import com.cd.university.common.utils.SpringUtil;
import com.cd.university.db.mapper.PaperExamineMapper;
import com.cd.university.db.mapper.PaperMapper;
import com.cd.university.db.pojo.Message;
import com.cd.university.db.pojo.Paper;
import com.cd.university.db.pojo.PaperExamine;
import com.cd.university.service.MessageService;
import com.cd.university.service.abs.AbstractAchievementProcessor;
import com.cd.university.vo.PaperExamineVo;
import com.cd.university.vo.ProjectExamineVo;
import com.cd.university.vo.UserVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @author 陈栋
 * @create 2021/11/3 16:50
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class PaperProcessor extends AbstractAchievementProcessor<Paper, PaperExamineVo>{

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private PaperExamineMapper paperExamineMapper;

    @Autowired
    private MessageService messageService;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void saveMessage(PaperExamineVo examineVo) {
        ProjectExamineVo vo = searchPEVoByProjectId(examineVo.getProjectId());
        messageService.submitFinalApplication(new Message(examineVo.getProjectId(),
                vo.getProjectName(),
                examineVo.getReviewerId(),
                UniversityConstants.PROJECT_ACHIEVEMENT_PAPER,
                examineVo.getPeriodicalId(),
                UniversityConstants.MESSAGE_STATUS_FINAL_APPLICATION));
    }

    @Override
    public Paper insertData(Object data) {
        // 将Object转成Paper对象
        Paper paper = objectMapper.convertValue(data, Paper.class);

        ProjectExamineVo projectExamineVo = super.searchPEVoByProjectId(paper.getProjectId());
        // 判断该项目的状态时否是3：也就是项目已经处于立项的状态
        if (!projectExamineVo.getStatusId().equals(UniversityConstants.PROJECT_STATUS_SECOND_PASS)){
            return null;
        }

        // 插入数据
        int row = paperMapper.insert(paper);

        if (row < 1) {
            throw new RuntimeException("上传论文文件失败");
        }

        if (!super.updateDbStatus(UniversityConstants.PROJECT_STATUS_SUCCESS_PROJECT, projectExamineVo.getProjectName())) {
            throw new RuntimeException("更新数据库失败");
        }
        PaperProcessor bean = SpringUtil.getBean(PaperProcessor.class);
        bean.updateRedisStatus(paper.getProjectId(),UniversityConstants.PROJECT_STATUS_SUCCESS_PROJECT, paper.getPaperId());

        return paper;
    }

    @Override
    @Async
    public PaperExamineVo generateVo(Paper data) {

        // 创建一个PaperExamineVo对象
        PaperExamineVo examineVo = new PaperExamineVo();
        BeanUtils.copyProperties(data,examineVo);
        examineVo.setExamineStatus("未审核");

        // 因为PaperExamineVo对象中有projectExamineVo对象，所以需要把projectExamineVo对象找到，根据projectId查找
        Integer projectId = data.getProjectId();
        ProjectExamineVo projectExamineVo = super.searchPEVoByProjectId(projectId);

        // 搜索负责人
        for (UserVo userVo : projectExamineVo.getTeam()) {
            if (userVo.getUserId().equals(data.getLeaderId())) {
                examineVo.setLeaderName(userVo.getUserRealname());
                break;
            }
        }


        // 向数据库中插入审核
        PaperExamine pojo = new PaperExamine();
        BeanUtils.copyProperties(examineVo,pojo);

        int row = paperExamineMapper.insertSelective(pojo);
        if (row < 1) {
            throw new RuntimeException("插入论文审核失败");
        }

        // 设置普通成员变量
        examineVo.setProjectExamineVo(projectExamineVo);
        examineVo.setPeId(pojo.getPeId());

        return examineVo;
    }

    @Override
    public List<PaperExamineVo> passedResults(List<PaperExamineVo> list) {
        ArrayList<PaperExamineVo> result = new ArrayList<>();
        for (PaperExamineVo examineVo : list) {
            if (!examineVo.getExamineStatus().equals("未审核")) {
                result.add(examineVo);
            }
        }
        return result;
    }

    @Override
    public void loadToRedis() {
        ValueOperations opsForValue = redisTemplate.opsForValue();
        List<PaperExamine> paperExamines = paperExamineMapper.searchAll();

        List<PaperExamineVo> paperExamineVos = new ArrayList<>();
        // 把PaperExamine转成PaperExamineVo对象放入redis中
        for (PaperExamine paperExamine : paperExamines) {
            PaperExamineVo vo = new PaperExamineVo();
            BeanUtils.copyProperties(paperExamine, vo);

            // 通过projectId找到projectExamineVo，并且设置到PaperExamineVo中
            ProjectExamineVo projectExamineVo = searchPEVoByProjectId(paperExamine.getProjectId());
            vo.setProjectExamineVo(projectExamineVo);

            // 设置负责人姓名
            for (UserVo userVo : projectExamineVo.getTeam()) {
                if (userVo.getUserId().equals(paperExamine.getLeaderId())) {
                    vo.setLeaderName(userVo.getUserRealname());
                    break;
                }
            }
            // 设置申请时间
            vo.setApplyTime(paperExamine.getApplyTime());

            paperExamineVos.add(vo);
        }

        // 放入到redis中
        opsForValue.getAndSet(repositoryName.get(getThisClassName()), paperExamineVos);
    }

    @Override
    public List<PaperExamineVo> searchExamineByName(String name) {
        List<PaperExamineVo> list = getValueFromRedis(getThisClassName());

        List<PaperExamineVo> result = new ArrayList<>();
        for (PaperExamineVo paperExamineVo : list) {
            if (paperExamineVo.getPaperName().contains(name)) {
                result.add(paperExamineVo);
            }
        }

        return result;
    }

    @Override
    public List<PaperExamineVo> searchByUserName(List<PaperExamineVo> list, String userName) {

        List<PaperExamineVo> result = new ArrayList<>();
        for (PaperExamineVo paperExamineVo : list) {
            if (paperExamineVo.getLeaderName()!=null && paperExamineVo.getLeaderName().contains(userName)) {
                result.add(paperExamineVo);
            }
        }

        return result;
    }

    @Override
    public RestResult approvedAchievement(Integer peId, Integer reviewerId) {
        PaperExamine examine = new PaperExamine();
        examine.setExamineStatus("审核通过");
        examine.setPeId(peId);
        examine.setReviewerId(reviewerId);
        examine.setApplyTime(new Date(System.currentTimeMillis()));

        PaperExamine paperExamine = paperExamineMapper.selectByPrimaryKey(peId);
        examine.setPaperId(paperExamine.getPaperId());
        if (paperExamine==null) {
            return RestResult.failure("论文的审核id有误，请重新检查");
        }
        Integer projectId = paperExamine.getProjectId();
        ProjectExamineVo projectExamineVo = searchPEVoByProjectId(projectId);

        // 更新数据库中的项目文件的状态,项目文件通过审核则为
        boolean dbProjectFileStatus = updateDbProjectFileStatus(projectId, UniversityConstants.PROJECT_FILE_PASS, examine.getPaperId());
        if (!dbProjectFileStatus) {
            return RestResult.failure("项目文件审核失败");
        }

        boolean status = updateDbStatus(UniversityConstants.PROJECT_STATUS_FINALIZE_PROJECT, projectExamineVo.getProjectName());
        if (!status) {
            return RestResult.failure("更新项目以及项目审核状态失败");
        }

        // 更新成果形式
        int row = paperExamineMapper.updateByPrimaryKeySelective(examine);
        if (row < 1) {
            throw  new RuntimeException("审核论文失败，请重试");
        }

        // 更新Redis
        PaperProcessor bean = SpringUtil.getBean(PaperProcessor.class);

        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            //存在事物，则注册事务同步处理
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    loadToRedis();
                    // 更新Redis中的项目、项目文件、项目审核中的内容
                    bean.updateRedisStatus(projectId,UniversityConstants.PROJECT_STATUS_FINALIZE_PROJECT,paperExamine.getPaperId());
                }
            });
        }

        bean.approveSaveMessage(projectId,
                projectExamineVo.getProjectName(),
                reviewerId,
                UniversityConstants.PROJECT_ACHIEVEMENT_AWARD,
                paperExamine.getPeriodicalId());
        return RestResult.success("审核论文成功");
    }
}
